#ifndef IDENTITY_H
#define IDENTITY_H

// TODO: for what?
#define DEFAULT_NONE           0xff
#define DEFAULT_THIS_OBJECT    0xfe

#define MAX_INSTRS 512

/* to speed up cleaning the hash table, and identify the union */
#define IHE_RESWORD    0x8000	/* reserved word */
#define IHE_EFUN       0x4000	/* efun name */
#define IHE_SIMUL      0x2000	/* active simul efun name */
#define IHE_PERMANENT  (IHE_RESWORD | IHE_EFUN | IHE_SIMUL)
#define TOKEN_MASK     0x0fff

/* for find_or_add_ident */
#define FOA_GLOBAL_SCOPE       0x1
#define FOA_NEEDS_MALLOC       0x2

typedef struct {
	short local_num, global_num, efun_num;
	short function_num, simul_num;
} defined_name_t;

typedef struct ident_hash_elem_s {
	char *name;
	short token; /* only flags */
	unsigned short sem_value; /* for these, a count of the ambiguity */
	struct ident_hash_elem_s *next;
	/* the fields above must correspond to struct keyword_t */
	struct ident_hash_elem_s *next_dirty;
	defined_name_t dn;
} ident_hash_elem_t;

typedef struct {
	char *word;
	unsigned short token;       /* flags here too */
	unsigned short sem_value;   /* semantic value for predefined tokens */
	ident_hash_elem_t *next;
	/* the fields above must correspond to struct ident_hash_elem */
	short min_args;		/* Minimum number of arguments. */
	short max_args;		/* Maximum number of arguments. */
	short ret_type;		/* The return type used by the compiler. */
	unsigned short arg_type1;	/* Type of argument 1 */
	unsigned short arg_type2;	/* Type of argument 2 */
	unsigned short arg_type3;	/* Type of argument 1 */
	unsigned short arg_type4;	/* Type of argument 2 */
	short arg_index;		/* Index pointing to where to find arg type */
	short Default;		/* an efun to use as default for last
				 * argument */
} keyword_t;

/*
 * Information about all instructions. This is not really needed as the
 * automatically generated efun_arg_types[] should be used.
 */
typedef struct {
    short max_arg, min_arg;  /* Can't use char to represent -1 */
    short type[4];	     /* need a short to hold the biggest type flag */
    short Default;
    short ret_type;
    char *name;
    int arg_index;
} instr_t;

extern keyword_t predefs[];
extern int efun_arg_types[];
extern int arrow_efun, evaluate_efun, this_efun, to_float_efun, to_int_efun, new_efun;

ident_hash_elem_t *find_or_add_ident(char *, int);
ident_hash_elem_t *find_or_add_perm_ident(char *);
ident_hash_elem_t *lookup_ident(char *);
void free_unused_identifiers(void);
void init_identifiers(void);

#endif
